import numpy as np
import pandas as pd
from scipy import stats

from cat_rfs.code.utils.sort_portfolios import sort_portfolios
from cat_rfs.code.utils.table import Table
from cat_rfs.code.utils.tools import save_stat


def print_table1(output='console', reconstruct_betas=False):
    # %% Primary markets
    df = pd.read_csv('cat_rfs/data/primary.csv', parse_dates=['maturity', 'settle_date'])

    cols = 9
    just = ['l', 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r']
    head = ['Variable', 'N', 'Mean', 'St Dev', 'Min', '25\\%', '50\\%', '75\\%', 'Max']
    widt = 'auto'

    df2 = df.copy()
    df2['er'] = df2['spread'] - df2['expected_loss']
    df2['time_to_maturity'] = (df2['maturity'] - df2['settle_date']) / np.timedelta64(1, 'M')

    df2 = df2[['size', 'time_to_maturity', 'spread', 'attachment_prob',
               'expected_loss', 'exhaustion_prob', 'er']]

    T = Table(cols, width=widt, justs=just, caption='Summary statistics',
              label='summary_stats', footer=None, float_specifiers='h')

    data = df2.describe().T.reset_index()

    ROWNAMES = {'size': 'Size (\\$ million)',
                'time_to_maturity': 'Term (months)',
                'spread': 'Spread (\\%)',
                'attachment_prob': 'Attachment probability (\\%)',
                'expected_loss': 'Expected loss (\\%)',
                'exhaustion_prob': 'Exhaustion probability (\\%)',
                'er': 'Expected excess return (\\%)'}

    data = data.replace(ROWNAMES)

    data['count'] = data['count'].astype(int).apply(lambda i: '{:,}'.format(i))
    T.add_panel(data, formatting="%.1f", supheaders=['Panel A: Bond characteristics (primary market)'],
                supheader_cols=[(1, cols)], headers=head)

    df = sort_portfolios(df, {'expected_loss': [0.2, 0.4, 0.6, 0.8]}, numeric_folio_names=True)
    data = df.groupby('expected_loss_portfolio')['spread'].describe().reset_index()
    data['count'] = data['count'].astype(int).apply(lambda i: '{:,}'.format(i))
    head2 = ['Quintile'] + head[1:]
    T.add_panel(data, formatting="%.1f", supheaders=['Panel B: Spreads by expected loss quintile (primary market)'],
                supheader_cols=[(1, cols)], headers=head2)

    # %% Secondary markets
    df2 = pd.read_csv('cat_rfs/data/secondary.csv', parse_dates=['date', 'current_maturity'])

    df2.loc[df2['sheet_yield'] > df2['sheet_yield'].quantile(q=0.99), 'sheet_yield'] = np.nan
    df2.loc[df2['act_yield'] > df2['act_yield'].quantile(q=0.99), 'act_yield'] = np.nan
    df2['sheet_dm'] = df2['sheet_yield'] - df2['bmk_yield'].fillna(0) / 100
    df2['trace_dm'] = df2['act_yield'] - df2['bmk_yield'].fillna(0) / 100

    turnover_zeros = stats.percentileofscore(df2['turnover'].dropna().values,
                                             df2.loc[df2['turnover'] > 0, 'turnover'].min())

    save_stat(turnover_zeros, 'turnover_zeros', formatting='%.1f', output=output)
    save_stat(100 - turnover_zeros, 'turnover_nonzeros', formatting='%.1f', output=output)

    df2.loc[df2['turnover'] > 0, 'turnover'].min()

    data = (df2[['turnover', 'sheet_dm', 'trace_dm']]*100).describe().T.reset_index()

    ROWNAMES = {'turnover': 'Turnover (\\%)',
                'sheet_dm': 'Discount margin$_{sheet}$ (\\%)',
                'trace_dm': 'Discount margin$_{trace}$ (\\%)'}

    data = data.replace(ROWNAMES)
    data['count'] = data['count'].astype(int).apply(lambda i: '{:,}'.format(i))
    T.add_panel(data, formatting="%.1f", supheaders=['Panel C: Secondary market'],
                supheader_cols=[(1, cols)], headers=head)

    # %% Betas
    df2 = pd.read_csv(f"cat_rfs/data/betas{'_reconstructed' if reconstruct_betas else ''}.csv",
                              parse_dates=['date'])

    data = df2[['beta_sheet']].describe().T.reset_index()

    ROWNAMES = {'beta_sheet': '$\\hat{\\beta}_{sheet}$'}
    data = data.replace(ROWNAMES)
    data['count'] = data['count'].astype(int).apply(lambda i: '{:,}'.format(i))


    T.add_panel(data, formatting="%.2f", supheaders=['Panel D: Simulated $\\hat{\\beta}$'],
                supheader_cols=[(1, cols)], headers=head)

    # %% Print
    if output == 'paper':
        T.print_table('cat_rfs/output/tables/table1.tex')
    else:
        T.print_table()

    pass
